/**
 * This is the class with the main function which will start the game server
 * and any server wide settings will be set here.
 * 
 */

package jogs;
import jogs.net.*;
import jogs.games.Game;
import java.util.Hashtable;
import java.util.Enumeration;
import java.util.logging.Logger;
import java.util.logging.Handler;
import java.util.logging.Level;
//import java.util.logging.FileHandler;
import java.util.logging.ConsoleHandler;
//import java.util.ArrayList;
//import java.util.*;
import jogs.db.*;

public class GameServer
{
	private static final Logger logger = Logger.getLogger(GameServer.class.getName()); 
	public static Handler handler = new ConsoleHandler();
	static
	{
		logger.addHandler(handler);
	}
	
	private Hashtable<String, Player>	players;	//Players connected to server
	private Hashtable<String, Game>   	games;   	//games currently being played
	//private Game 						game;
	private TogServer 					server;		//Thread listening for new connections
	private boolean 					on;			//tell if server is still on
	private DB    					    db;			//Database connection
	
	/**
	 * Contructor which initialzes Datastructures
	 * and starts listening for connections
	 */
	public GameServer()
	{
		on = true;
		db = new JogsDB();
		players = new Hashtable<String, Player>();
		games = new Hashtable<String, Game>();
		//game = Game.newGame("test", "crazyeights", this, 8);
		server = new TogServer(10000, this);
		server.start();
	}
	
	public GameServer(DB newdb)
	{
		on = true;
		db = newdb;
		players = new Hashtable<String, Player>();
		games = new Hashtable<String, Game>();
		//game = Game.newGame("test", "crazyeights", this, 8);
		server = new TogServer(10000, this);
		server.start();
	}
	
	/*public GameServer(String gameType, int port, String gameName, Hashtable<String, String> conf)
	{
		int numPlayers = Integer.parseInt(conf.get("players"));
		on = true;
		db = new JogsDB(gameName);
		players = new Hashtable<String, Player>();
		games = new Hashtable<String, Game>();
		//players = new ArrayList<Player>();
		//game = Game.newGame(gameName, gameType, this, numPlayers);
		db.addTable(gameType, numPlayers);
		server = new TogServer(port, this);
		server.start();
	}*/
	
	//GAME METHODS
	//===========================================================
	public Game getGame(String gameName)
	{
		return games.get(gameName);
	}
	
	public Hashtable<String, Game> getGames()
	{
		return games;
	}
		
	public Game createGame(String gameType, String tableName, int max, Player player)
	{
		Game g = Game.newGame(tableName, gameType, this, max);
		if(g != null)
		{
			games.put(tableName, g);
			db.addTable(gameType, max, tableName);
			//tell everybody a new game is created.
			sendAll("@NEWGAME:" + g.getStatus());
			logger.log(Level.INFO, "Game " + tableName + " started");
		}
		else
		{
			logger.log(Level.WARNING, "Game " + tableName + " did not start");
		}
		return g;
	}
	
	public void removeGame(String tableName)
	{
		Game g = games.get(tableName);
		g.close();
		db.updateStatus(4, tableName);
		sendAll("@GAMEOVER:" + tableName);
		games.remove(tableName);
	}
	
	public void joinGame(String game, Player p)
	{
		Game g = games.get(game);
		if(g.join(p))
		{
			String status = g.getStatus();
			String[] params = status.split(","); 
			sendAll("@STATUS:" + status);
			db.addPlayer(p.getName(), Integer.parseInt(params[3]), g.getName());
		}
	}
	
	public void leaveGame(String game, Player p)
	{
		Game g = games.get(game);
		g.leave(p);
		int i = g.getNumPlayers();
		if(i >= 0)
			removeGame(g.getName());
		else
			sendAll("@STATUS:" + g.getStatus());
	}
	
	public void statusChange(String tableName)
	{
		String status = games.get(tableName).getStatus();
		sendAll("@STATUS:" + status);
		String[] params = status.split(",");
		db.updateStatus(Integer.parseInt(params[4]), tableName);
		
	}
		
	
	//PLAYER METHODS
	//===================================================================
	
	public void addPlayer(String playerName, Player player)
	{
		players.put(playerName, player);
		sendAll("@NEWPLAYER:" + playerName);
		String allPlayers = "";
		for ( Enumeration<String> e = players.keys(); e.hasMoreElements(); )
		{
		   String value = e.nextElement();
		   allPlayers += value + ",";
		   
		}
		
		player.send("@ALLPLAYERS:" + allPlayers);
		
		for(Game g : games.values())
		{
			player.send("@STATUS:" + g.getStatus());
		}
	}
	
	public void removePlayer(String playerName)
	{
		players.remove(playerName);
		sendAll("@PLAYERDISC:" + playerName);
	}
	
	public void sendAll(String message)
	{
		for(Player p:players.values())
		{
			p.send(message);
		}
	}
	
	//OTHER METHODS
	//===============================================================
	
	public DB getDB()
	{
		return db;
	}
	
	/**
	 * tells if the server is still on.
	 * return true is server is still running
	 * and false of it is not.
	 * @return 
	 */
	public boolean isOn()
	{
		return on;
	}
	
	public void exit()
	{
		server.close();
		db.close();
		//game.close();
		for(Player p : players.values())
		{
			p.close();
			players.remove(p);
		}
		on = false;
	}

	/**
	 * Main method which will start server.
	 * @param args
	 */
	public static void main(String[] args)
	{
		DummyDB db = new DummyDB();
		GameServer gs = new GameServer(db);
		while (gs.isOn())
		{
			continue;
		}
	}

}
